<?php

namespace App\Service\Impl;

use App\Tools\Auxi;
use Phoenix\Log\Log4p as logger;
use Phoenix\Api\Gateway;
use App\Service\WeiXin;
use Phoenix\Log\Log4p;

if (!defined('IN_PX')) {
    exit;
}

class WeiXinImpl implements WeiXin {

    const VERSION = '1.2.0';

    protected function __Value($setting) {}

    private function __Inject($db, $cache, $session) {}

//    public $appid = 'wx6f4ad344322d6b5f';
//    private $_appsecret = '76b4d6f2c5f04699d16a8b93f57ea089';

    public $appid = 'wxce81b934e443ce88';
    private $_appsecret = 'e312504983f837ed77ca5c1aad9f02dc';

    //测试号appID
    private $_redirectUri = 'http://www.bondent.net/wechat/bind';
    public $cookieExpire = 20;
    private $_cookieid = 'bondent';

    public function getUserOs() {
        $_userAgent = $_SERVER['HTTP_USER_AGENT'];
        $_out = 'other';
        if (stristr($_userAgent, 'Android')) {
            $_out = 'Android';
        } else if (stristr($_userAgent, 'iPhone')) {
            $_out = 'iPhone';
        }
        return $_out;
    }

    public function getBaseinfo($code) {
        $post = array(
            'appid' => $this->appid,
            'secret' => $this->_appsecret,
            'code' => $code,
            'grant_type' => 'authorization_code'
        );
        $_json = json_decode($this->curl('https://api.weixin.qq.com/sns/oauth2/access_token', $post, 'GET'), true);
        if (isset($_json['errcode'])) {
            return false;
        }
        return $_json;
    }

    public function getUserinfo($baseRs) {

        $post = array(
            'access_token' => $baseRs['access_token']
        , 'openid' => $baseRs['openid']
        , 'lang' => 'zh_CN',
        );

        $_json = json_decode($this->curl('https://api.weixin.qq.com/sns/userinfo', $post, 'GET'), true);

        if (isset($_json['errcode'])) {
            logger::error($_json);
            return false;
        } else {
            return $_json;
        }
    }

    public function saveUserInfo($code) {
        if (false !== ($_baseinfo = $this->getBaseinfo($code))) {
            $_openid = $_baseinfo['openid'];
            $time = time();
            if (!($_rs = $this->findMember($_openid))) {
                $_token = $_baseinfo['access_token'];
                $post = array(
                    'access_token' => $_token
                , 'openid' => $_openid
                , 'lang' => 'zh_CN'
                );
                $return = $this->curl('https://api.weixin.qq.com/sns/userinfo', $post, 'GET');
                logger::debug($return);
                $_json = json_decode($return, true);
                return $_json;
            } else {
                $_json = array();
                $_json['openid'] = $_rs->openid;
                $_json['nickname'] = $_rs->nickname;
                $_json['headimgurl'] = $_rs->headimgurl;
                return $_json;
            }
        }
        return false;
    }

    //微信昵称过滤
    private function filter($str) {
        if($str){
            $name = $str;
            $name = preg_replace('/\xEE[\x80-\xBF][\x80-\xBF]|\xEF[\x81-\x83][\x80-\xBF]/', '', $name);
            $name = preg_replace('/xE0[x80-x9F][x80-xBF]‘.‘|xED[xA0-xBF][x80-xBF]/S','?', $name);
            $return = json_decode(preg_replace("#(\\\ud[0-9a-f]{3})#ie","",json_encode($name)));
            if(!$return){
                return 'bondent'. mt_rand(100, 999);
            }
        }else{
            $return = '';
        }
        return $return;
    }

    private function _setUserCookie($openid) {
        setcookie($this->_cookieid, $openid, time() + 24 * 3600 * $this->cookieExpire, '/', '');
    }

    /**
     * curl访问ucenter url 默认只获取header
     * @param type $ucphp ucenter接口url
     * @param type $getHeader 是否将header返回
     * @param type $getBody true返回 false不返回
     * @return boolean
     */
    public function curl($url, $post = null, $method = 'POST', $getHeader = false) {
        if (!$url) {
            return false;
        }

        $_headerArray = array(
            'Accept:text/html, application/xhtml+xml, application/javascript, */*'
        , 'Content-Type:application/x-www-form-urlencoded',
//            , 'Referer:https://mp.weixin.qq.com/'
        );
        if ($method == 'GET' && !is_null($post)) {
            $url .= '?' . http_build_query($post);
        }

        $_ch = curl_init();
        curl_setopt($_ch, CURLOPT_URL, $url);
        curl_setopt($_ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($_ch, CURLOPT_HEADER, $getHeader);
        curl_setopt($_ch, CURLOPT_SSL_VERIFYPEER, false);
        if ($method == 'POST' && !is_null($post)) {
            curl_setopt($_ch, CURLOPT_POSTFIELDS, $post);
        }
        $_output = curl_exec($_ch);
        curl_close($_ch);
        return $_output;
    }

    /**
     *  获取cookie ,不做跳转
     */
    public function getWinxinCookie($_cookieid) {
        $_rs = null;
        if (isset($_COOKIE[$_cookieid])) {
            list($_rs['openid'], $_rs['userId']) = explode(',', $_COOKIE[$_cookieid]);
        }
        return $_rs;
    }

    private function findExists($openId) {
        return $this->db->table('#@__@member')
            ->where('openid = ?')
            ->bind(array($openId))
            ->exists();
    }

    private function findMember($openId) {
        return $this->db->select('*')
            ->table('#@__@member')
            ->where('openid = ?')
            ->bind(array($openId))
            ->find();
    }

    public function code() {
            $urlObj["appid"] = $this->appid;
            $urlObj["redirect_uri"] = urlencode($this->_redirectUri);
            $urlObj["response_type"] = "code";
            $urlObj["scope"] = "snsapi_base";
            $urlObj["state"] = "STATE"."#wechat_redirect";
            $bizString = $this->ToUrlParams($urlObj);
            return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;

    }

    private function ToUrlParams($urlObj)
    {
        $buff = "";
        foreach ($urlObj as $k => $v)
        {
            if($k != "sign"){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }


    public function getOpenid($rm, $isUseCookie = true) {
        if ($isUseCookie && isset($_COOKIE[$this->_cookieid])) {
            $_cookieid = explode(',', $_COOKIE[$this->_cookieid]);
            return $_cookieid[0];
        } else if (isset($_GET['state'])) {
            if (isset($_GET['code']) && $_GET['code'] != '' && (false === $this->cache->get($_GET['code']))) {
                $this->cache->set($_GET['code'], 'x'); // 缓存中写入首次请求的 code , 之后的请求不处理
                $_json = null;
                $_GET['state'] = explode(',', $_GET['state']);
                switch ($_GET['state'][1]) {
                    case 'base' :
                        if (false !== ($_json = $this->getBaseinfo($_GET['code']))) { //base 只获取到token和openid
                            //查看数据库中是否存在此会员
                            $_rs = $this->findMember($_json['openid']);
                            if (count($_rs)) {
                                //$this->_setSession($_rs);
                                $this->_setUserCookie($_json['openid']);
                                $this->session->member = array(
                                    'member_id' => $_rs->member_id,
                                );
                                header('Location: /member/center');exit;
                            }
                            //不存在此用户，重新授权获取用户信息
                            $_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $this->appid
                                . "&lang=zh_CN&redirect_uri=" . urlencode($this->_redirectUri)
                                . "&response_type=code&scope=snsapi_userinfo&state={$rm},userinfo#wechat_redirect";
                            header('Location: ' . $_url);
                            exit;
                        }
                        break;
                    case 'userinfo' :
                        $_json = $this->saveUserInfo($_GET['code']);
                        if (false !== $_json) {
                            $this->cache->delete($_GET['code']);
                            return $_json;
                        }
                        break;
                }
            }
            return false;
        } else {
            //return 'oFT73vxfqBzsY5PZ4I4Q_hiDNBOU';
            $_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $this->appid
                . "&lang=zh_CN&redirect_uri=" . urlencode($this->_redirectUri)
                . "&response_type=code&scope=snsapi_userinfo&state={$rm},userinfo#wechat_redirect";
            header('Location: ' . $_url);
            exit;
        }
    }

    /**
     * accessToken
     * @return bool
     */
    public function getAccessToken() {

        $post = array(
            'grant_type' => 'client_credential'
        , 'appid' => $this->appid
        , 'secret' => $this->_appsecret,
        );
        $_tmp = array(
            'token' => ''
        , 'createtime' => '',
        );
        $_timelimit = 7000;
        $_cacheId = 'accessTokenh5';
        if (false !== ($_tmp = $this->cache->get($_cacheId)) && time() - intval($_tmp['createtime']) < $_timelimit) {
            logger::debug(time() - intval($_tmp['createtime']));
            return $_tmp['token'];
        }

        if (($_json = json_decode($this->curl('https://api.weixin.qq.com/cgi-bin/token', $post, 'GET'), true)) !== false &&
            isset($_json['access_token'])
        ) {
            $_tmp = array(
                'token' => $_json['access_token']
            , 'createtime' => time(),
            );
            $this->cache->set($_cacheId, $_tmp);
            return $_json['access_token'];
        }
        logger::debug('b' . json_encode($_json));
        return false;
    }

    /* ===============================
     *
     *  JSSDK 2015年1月13日17:54:05
     *
    ============================== */

    public function getSignPackage($url = '') {
        $jsapiTicket = $this->getJsApiTicket();
        if ($url == '') {
            $url = "http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
        }

        //$url = self::$redirectUri . "?state=card_{$_SERVER['REQUEST_URI']}";

        $timestamp = time();
        $nonceStr = $this->createNonceStr();

        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket={$jsapiTicket}&noncestr={$nonceStr}&timestamp={$timestamp}&url={$url}";

        $signature = sha1($string);

        $signPackage = array(
            "appId" => $this->appid,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $signature,
            "rawString" => $string,
        );
        return $signPackage;
    }

    private function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    public function getJsApiTicket() {
        $accessToken = $this->getAccessToken();
        logger::debug('ticket');
        $post = array(
            'type' => 'jsapi'
        , 'access_token' => $accessToken
        , 'appid' => $this->appid
        , 'secret' => $this->_appsecret,
        );
        $_tmp = array(
            'ticket' => ''
        , 'createtime' => '',
        );
        $_timelimit = 7000;
        $_cacheId = 'jsapi_ticketh5';

        $this->cache->set('123456today', '123456aaa');
        logger::debug('359获取了缓存');
        logger::debug($this->cache->get('123456today'));
        logger::debug('缓存中写入首次请求的');
        logger::debug($this->cache->get('123456today'));

        if (false !== ($_tmp = $this->cache->get($_cacheId)) && (time() - intval($_tmp['createtime']) < $_timelimit)) {
            logger::debug('有缓存');
            logger::debug($_tmp);
            logger::debug(time() - intval($_tmp['createtime']));
            return $_tmp['ticket'];
        }

        if (($_json = json_decode($this->curl('https://api.weixin.qq.com/cgi-bin/ticket/getticket', $post, 'GET'), true)) !== false &&
            isset($_json['ticket'])
        ) {
            $_tmp = array(
                'ticket' => $_json['ticket']
            , 'createtime' => time(),
            );
            $this->cache->set($_cacheId, $_tmp);
            logger::debug('357设置缓存了');
            $this->cache->set('123456today', '123456aaa');
            logger::debug('359获取了缓存');
            logger::debug($this->cache->get('123456today'));
            return $_json['ticket'];
        }
        logger::debug($_json);
        return false;
    }
}
